
#include   "tx_api.h"
#include   "nx_api.h"
extern void    test_control_return(UINT status);

#if !defined(NX_DISABLE_UDP_TX_CHECKSUM) && !defined(NX_DISABLE_IPV4)
#include   "nxd_dhcp_client.h"
#include   "nxd_dhcp_server.h"

#define     DEMO_STACK_SIZE             4096
#define     NX_PACKET_SIZE              1536
#define     NX_PACKET_POOL_SIZE         NX_PACKET_SIZE * 8
                                                               
#define     NX_DHCP_SERVER_IP_ADDRESS_0 IP_ADDRESS(192, 168, 3, 8)   
#define     START_IP_ADDRESS_LIST_0     IP_ADDRESS(192, 168, 3, 11)
#define     END_IP_ADDRESS_LIST_0       IP_ADDRESS(192, 168, 3,20)

#define     NX_DHCP_SUBNET_MASK_0       IP_ADDRESS(255,255,255,0)
#define     NX_DHCP_DEFAULT_GATEWAY_0   IP_ADDRESS(192, 168, 3, 8)
#define     NX_DHCP_DNS_SERVER_0        IP_ADDRESS(192, 168, 3, 8)

/* Define the ThreadX and NetX object control blocks...  */
static TX_THREAD               client_thread;
static NX_PACKET_POOL          client_pool;
static NX_IP                   client_ip;

static TX_THREAD               server_thread;
static NX_PACKET_POOL          server_pool;
static NX_IP                   server_ip;
static NX_DHCP_SERVER          dhcp_server;

/* Define the counters used in the demo application...  */

static ULONG                   error_counter;
static ULONG                   resposner_counter;
static CHAR                    *pointer;  

/* Define thread prototypes.  */

static void    server_thread_entry(ULONG thread_input);
static void    client_thread_entry(ULONG thread_input);

/******** Optionally substitute your Ethernet driver here. ***********/
extern void    _nx_ram_network_driver_1024(struct NX_IP_DRIVER_STRUCT *driver_req);  
extern UINT    (*advanced_packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
static UINT    my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
           

/* Frame (342 bytes)  DHCP DISCOVER  */
static const unsigned char pkt1[342] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, /* .......P */
0xb6, 0x07, 0xa1, 0x69, 0x08, 0x00, 0x45, 0x00, /* ...i..E. */
0x01, 0x48, 0x00, 0x01, 0x00, 0x00, 0x80, 0x11, /* .H...... */
0x39, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, /* 9....... */
0xff, 0xff, 0x00, 0x44, 0x00, 0x43, 0x01, 0x34, /* ...D.C.4 */
0x83, 0x9e, 0x01, 0x01, 0x06, 0x00, 0x00, 0xf6, /* ........ */
0x16, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, /* .......P */
0xb6, 0x07, 0xa1, 0x69, 0x00, 0x00, 0x00, 0x00, /* ...i.... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */
0x53, 0x63, 0x35, 0x01, 0x01, 0x3d, 0x07, 0x01, /* Sc5..=.. */
0x00, 0x50, 0xb6, 0x07, 0xa1, 0x69, 0x0c, 0x0e, /* .P...i.. */
0x43, 0x57, 0x2d, 0x39, 0x57, 0x44, 0x50, 0x4a, /* CW-9WDPJ */
0x56, 0x31, 0x2d, 0x47, 0x41, 0x31, 0x3c, 0x08, /* V1-GA1<. */
0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, /* MSFT 5.0 */
0x37, 0x0c, 0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, /* 7.....,. */
0x2f, 0x1f, 0x21, 0x79, 0xf9, 0x2b, 0xff, 0x00, /* /.!y.+.. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00              /* ...... */
};

/* Frame (342 bytes)  DHCP OFFER  */
static const unsigned char pkt2[342] = {
0x00, 0x50, 0xb6, 0x07, 0xa1, 0x69, 0x00, 0x08, /* .P...i.. */
0xee, 0x03, 0x6a, 0xc6, 0x08, 0x00, 0x45, 0x00, /* ..j...E. */
0x01, 0x48, 0x00, 0x01, 0x40, 0x00, 0x80, 0x11, /* .H..@... */
0x72, 0x40, 0xc0, 0xa8, 0x03, 0x08, 0xc0, 0xa8, /* r@...... */
0x03, 0x0b, 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, /* ...C.D.4 */
0x54, 0xf8, 0x02, 0x01, 0x06, 0x00, 0x00, 0xf6, /* T....... */
0x16, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0xc0, 0xa8, 0x03, 0x0b, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, /* .......P */
0xb6, 0x07, 0xa1, 0x69, 0x00, 0x00, 0x00, 0x00, /* ...i.... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */
0x53, 0x63, 0x35, 0x01, 0x02, 0x36, 0x04, 0xc0, /* Sc5..6.. */
0xa8, 0x03, 0x08, 0x01, 0x04, 0xff, 0xff, 0xff, /* ........ */
0x00, 0x03, 0x04, 0xc0, 0xa8, 0x03, 0x08, 0x06, /* ........ */
0x04, 0xc0, 0xa8, 0x03, 0x08, 0x33, 0x04, 0x00, /* .....3.. */
0x00, 0x27, 0x10, 0x3a, 0x04, 0x00, 0x00, 0x13, /* .'.:.... */
0x88, 0x3b, 0x04, 0x00, 0x00, 0x22, 0x2e, 0xff, /* .;...".. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00              /* ...... */
};

/* Frame (379 bytes) DHCP REQUEST  */
static const unsigned char pkt3[379] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, /* .......P */
0xb6, 0x07, 0xa1, 0x69, 0x08, 0x00, 0x45, 0x00, /* ...i..E. */
0x01, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x80, 0x11, /* .m...... */
0x39, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, /* 9....... */
0xff, 0xff, 0x00, 0x44, 0x00, 0x43, 0x01, 0x59, /* ...D.C.Y */
0x4d, 0x72, 0x01, 0x01, 0x06, 0x00, 0x00, 0xf6, /* Mr...... */
0x16, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, /* .......P */
0xb6, 0x07, 0xa1, 0x69, 0x00, 0x00, 0x00, 0x00, /* ...i.... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */
0x53, 0x63, 0x35, 0x01, 0x03, 0x3d, 0x07, 0x01, /* Sc5..=.. */
0x00, 0x50, 0xb6, 0x07, 0xa1, 0x69, 0x32, 0x04, /* .P...i2. */
0xc0, 0xa8, 0x03, 0x0b, 0x36, 0x04, 0xc0, 0xa8, /* ....6... */
0x03, 0x08, 0x0c, 0x0e, 0x43, 0x57, 0x2d, 0x39, /* ....CW-9 */
0x57, 0x44, 0x50, 0x4a, 0x56, 0x31, 0x2d, 0x47, /* WDPJV1-G */
0x41, 0x31, 0x51, 0x1e, 0x00, 0x00, 0x00, 0x43, /* A1Q....C */
0x57, 0x2d, 0x39, 0x57, 0x44, 0x50, 0x4a, 0x56, /* W-9WDPJV */
0x31, 0x2d, 0x47, 0x41, 0x31, 0x2e, 0x54, 0x54, /* 1-GA1.TT */
0x50, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x63, /* PGroup.c */
0x6f, 0x6d, 0x3c, 0x08, 0x4d, 0x53, 0x46, 0x54, /* om<.MSFT */
0x20, 0x35, 0x2e, 0x30, 0x37, 0x0c, 0x01, 0x0f, /*  5.07... */
0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21, 0x79, /* ..,./.!y */
0xf9, 0x2b, 0xff                                /* .+. */
};      
       
/* Frame (342 bytes)  DHCP ACK  */
static const unsigned char pkt4[342] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x08, /* ........ */
0xee, 0x03, 0x6a, 0xc6, 0x08, 0x00, 0x45, 0x00, /* ..j...E. */
0x01, 0x48, 0x00, 0x02, 0x40, 0x00, 0x80, 0x11, /* .H..@... */
0x72, 0x3f, 0xc0, 0xa8, 0x03, 0x08, 0xc0, 0xa8, /* r?...... */
0x03, 0x0b, 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, /* ...C.D.4 */
0x51, 0xf8, 0x02, 0x01, 0x06, 0x00, 0x00, 0xf6, /* Q....... */
0x16, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0xc0, 0xa8, 0x03, 0x0b, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, /* .......P */
0xb6, 0x07, 0xa1, 0x69, 0x00, 0x00, 0x00, 0x00, /* ...i.... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */
0x53, 0x63, 0x35, 0x01, 0x05, 0x36, 0x04, 0xc0, /* Sc5..6.. */
0xa8, 0x03, 0x08, 0x01, 0x04, 0xff, 0xff, 0xff, /* ........ */
0x00, 0x03, 0x04, 0xc0, 0xa8, 0x03, 0x08, 0x06, /* ........ */
0x04, 0xc0, 0xa8, 0x03, 0x08, 0x33, 0x04, 0x00, /* .....3.. */
0x00, 0x27, 0x10, 0x3a, 0x04, 0x00, 0x00, 0x13, /* .'.:.... */
0x88, 0x3b, 0x04, 0x00, 0x00, 0x22, 0x2e, 0xff, /* .;...".. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00              /* ...... */
};

/* Define what the initial system looks like.  */

#ifdef CTEST
VOID test_application_define(void *first_unused_memory)
#else
void    netx_dhcp_server_test_application_define(void *first_unused_memory)
#endif
{

UINT    status;


    /* Setup the working pointer.  */
    pointer =  (CHAR *) first_unused_memory;

    /* Create the client thread.  */
    tx_thread_create(&client_thread, "thread client", client_thread_entry, 0,  
            pointer, DEMO_STACK_SIZE, 
            4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
    pointer =  pointer + DEMO_STACK_SIZE;

    /* Create the server thread.  */
    tx_thread_create(&server_thread, "thread server", server_thread_entry, 0,  
            pointer, DEMO_STACK_SIZE, 
            3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
    pointer =  pointer + DEMO_STACK_SIZE;

    /* Initialize the NetX system.  */
    nx_system_initialize();

    /* Create the client packet pool.  */
    status =  nx_packet_pool_create(&client_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
    pointer = pointer + NX_PACKET_POOL_SIZE;

    /* Check for pool creation error.  */
    if (status)
        error_counter++;
    
    /* Create the server packet pool.  */
    status =  nx_packet_pool_create(&server_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
    pointer = pointer + NX_PACKET_POOL_SIZE;

    /* Check for pool creation error.  */
    if (status)
        error_counter++;

    /* Create an IP instance for the DHCP Client.  */
    status = nx_ip_create(&client_ip, "DHCP Client", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &client_pool, _nx_ram_network_driver_1024, pointer, 2048, 1);

    pointer =  pointer + 2048;

    /* Check for IP create errors.  */
    if (status)
        error_counter++;
    
    /* Create an IP instance for the DHCP Server.  */
    status = nx_ip_create(&server_ip, "DHCP Server", NX_DHCP_SERVER_IP_ADDRESS_0, 0xFFFFFF00UL, &server_pool, _nx_ram_network_driver_1024, pointer, 2048, 1);

    pointer =  pointer + 2048;

    /* Check for IP create errors.  */
    if (status)
        error_counter++;

    /* Enable ARP and supply ARP cache memory for DHCP Client IP.  */
    status =  nx_arp_enable(&client_ip, (void *) pointer, 1024);
    pointer = pointer + 1024;

    /* Check for ARP enable errors.  */
    if (status)
        error_counter++;
    
    /* Enable ARP and supply ARP cache memory for DHCP Server IP.  */
    status =  nx_arp_enable(&server_ip, (void *) pointer, 1024);
    pointer = pointer + 1024;

    /* Check for ARP enable errors.  */
    if (status)
        error_counter++;

    /* Enable UDP traffic.  */
    status =  nx_udp_enable(&client_ip);

    /* Check for UDP enable errors.  */
    if (status)
        error_counter++;
    
    /* Enable UDP traffic.  */
    status =  nx_udp_enable(&server_ip);

    /* Check for UDP enable errors.  */
    if (status)
        error_counter++;

    /* Enable ICMP.  */
    status =  nx_icmp_enable(&client_ip);

    /* Check for errors.  */
    if (status)
        error_counter++;

    /* Enable ICMP.  */
    status =  nx_icmp_enable(&server_ip);

    /* Check for errors.  */
    if (status)
        error_counter++;

    return;
}

/* Define the test threads.  */

void    server_thread_entry(ULONG thread_input)
{

UINT        status;
UINT        iface_index;
UINT        addresses_added;

    printf("NetX Test:   DHCP Server Test..........................................");

    /* Create the DHCP Server.  */
    status =  nx_dhcp_server_create(&dhcp_server, &server_ip, pointer, DEMO_STACK_SIZE, 
                                   "DHCP Server", &server_pool);
    
    pointer = pointer + DEMO_STACK_SIZE;
    
    /* Check for errors creating the DHCP Server. */
    if (status)
        error_counter++;

    /* Load the assignable DHCP IP addresses for the first interface.  */
    iface_index = 0;

    status = nx_dhcp_create_server_ip_address_list(&dhcp_server, iface_index, START_IP_ADDRESS_LIST_0, 
                                                   END_IP_ADDRESS_LIST_0, &addresses_added);

    /* Check for errors creating the list. */
    if (status)
    {
        error_counter++;
    }

    /* Verify all the addresses were added to the list. */
    if (addresses_added != 10)
    {
        error_counter++;
    }

    status = nx_dhcp_set_interface_network_parameters(&dhcp_server, iface_index, NX_DHCP_SUBNET_MASK_0, 
                                                      NX_DHCP_DEFAULT_GATEWAY_0, NX_DHCP_DNS_SERVER_0);

    /* Check for errors setting network parameters. */
    if (status)
    {
        error_counter++;
    }

    /* Start DHCP Server task.  */
    status = nx_dhcp_server_start(&dhcp_server);

    /* Check for errors starting up the DHCP server.  */
    if (status)
    {
        error_counter++;
    }
    
    tx_thread_sleep(1 * NX_IP_PERIODIC_RATE);

    if ((error_counter) || (resposner_counter != 2))
    {
        printf("ERROR!\n");                                 
        test_control_return(1);
    }
    else
    {
        printf("SUCCESS!\n");
        test_control_return(0);
    }

    return;
}

/* Define the test threads.  */

void    client_thread_entry(ULONG thread_input)
{                      
UINT        status;
NX_PACKET   *my_packet;     

    /* Send the DHCP DISCOVER packet.  */  
    status = nx_packet_allocate(&client_pool, &my_packet, NX_UDP_PACKET, NX_WAIT_FOREVER);

    /* Check status */
    if(status)
        error_counter ++;
                                   
    /* Set the callback function to process the DHCP Message packet.  */
    advanced_packet_process_callback = my_packet_process;    

    /* Fill in the packet with data. Skip the MAC header.  */
    memcpy(my_packet -> nx_packet_prepend_ptr, &pkt1[14], sizeof(pkt1) - 14);
    my_packet -> nx_packet_length = sizeof(pkt1) - 14;
    my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + sizeof(pkt1) - 14;

    /* Directly receive the DHCP DISCOVER packet.  */
    _nx_ip_packet_deferred_receive(&server_ip, my_packet);     
}

static UINT    my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr)
{                 

UINT        status;
NX_PACKET   *my_packet;

    if ((ip_ptr == &server_ip) && (packet_ptr ->nx_packet_length >= 300))
    {

        resposner_counter ++;

        if (resposner_counter == 1)
        {          

            /* Check the DHCP OFFER.  */
#ifdef NX_ENABLE_IP_ID_RANDOMIZATION
            /* Skip IP id when it is random. */
            if (memcmp(packet_ptr ->nx_packet_prepend_ptr, &pkt2[14], 4) ||
                memcmp(packet_ptr ->nx_packet_prepend_ptr + 6, &pkt2[20], 4) ||
                memcmp(packet_ptr ->nx_packet_prepend_ptr + 12, &pkt2[26], sizeof(pkt2) - 26))
#else
            if (memcmp(packet_ptr ->nx_packet_prepend_ptr, &pkt2[14], sizeof(pkt2) -14))
#endif
                error_counter ++;

            /* Send the DHCP REQUEST.  */  
            status = nx_packet_allocate(&client_pool, &my_packet, NX_UDP_PACKET, NX_WAIT_FOREVER);

            /* Check status */
            if(status)
                error_counter ++;

            /* Fill in the packet with data. Skip the MAC header.  */
            memcpy(my_packet -> nx_packet_prepend_ptr, &pkt3[14], sizeof(pkt3) - 14);
            my_packet -> nx_packet_length = sizeof(pkt3) - 14;
            my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + sizeof(pkt3) - 14;

            /* Directly receive the DHCP REQUEST packet.  */
            _nx_ip_packet_deferred_receive(&server_ip, my_packet);     
        }  
        else if (resposner_counter == 2)
        {          

            /* Check the DHCP ACK.  */
#ifdef NX_ENABLE_IP_ID_RANDOMIZATION
            /* Skip IP id when it is random. */
            if (memcmp(packet_ptr -> nx_packet_prepend_ptr, &pkt4[14], 4) ||
                memcmp(packet_ptr -> nx_packet_prepend_ptr + 6, &pkt4[20], 4) ||
                memcmp(packet_ptr -> nx_packet_prepend_ptr + 12, &pkt4[26], sizeof(pkt4) - 26))
#else
            if (memcmp(packet_ptr -> nx_packet_prepend_ptr, &pkt4[14], sizeof(pkt4) -14))
#endif
                error_counter ++;        
        }    ;    
    }
                                     
    return NX_TRUE;
}
#else
#ifdef CTEST
VOID test_application_define(void *first_unused_memory)
#else
void    netx_dhcp_server_test_application_define(void *first_unused_memory)
#endif
{
    printf("NetX Test:   DHCP Server Test..........................................N/A\n");
    test_control_return(3);
}
#endif
